﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.IO;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media.Imaging;
using System.Xml;
using SHomeWorkshop.LunarMind.Adorners;
using Microsoft.Win32;
using System.Windows.Media;
using SHomeWorkshop.LunarConcept.Controls;
using SHomeWorkshop.LunarConcept;

namespace SHomeWorkshop.LunarMind
{
    public class TitleImage : AdornerDecorator, INotifyPropertyChanged
    {
        public TitleImage(MainWindow editor, Title masterTitle)
        {
            this.editor = editor;
            this.masterTitle = masterTitle;
            this.Child = this.baseBorder;
            this.baseBorder.Child = this.baseViewBox;

            this.RebuildANewID();

            //初始化快捷菜单
            this.ContextMenu = this.contextMenu;

            MenuItem miLoadImage = new MenuItem() { Header = "载入位图文件(_B)", };
            miLoadImage.Click += miLoadImage_Click;
            this.contextMenu.Items.Add(miLoadImage);

            MenuItem miImageTitle = new MenuItem() { Header = "设置标题文本(_T)", };
            miImageTitle.Click += miImageTitle_Click;
            this.contextMenu.Items.Add(miImageTitle);

            this.contextMenu.Items.Add(new Separator());

            MenuItem miPresentateImage = new MenuItem() { Header = "查看图像(_P)", };
            miPresentateImage.Click += miPresentateImage_Click;
            contextMenu.Items.Add(miPresentateImage);

            MenuItem miPresentateAllImage = new MenuItem() { Header = "查看所有图像(_A)", InputGestureText = "F6" };
            miPresentateAllImage.Click += miPresentateAllImage_Click;
            contextMenu.Items.Add(miPresentateAllImage);

            this.contextMenu.Items.Add(new Separator());

            miDefaultMode = new MenuItem() { Header = "原始尺寸(_O)", IsChecked = true, };
            miDefaultMode.Click += miDefaultMode_Click;
            this.contextMenu.Items.Add(miDefaultMode);

            miSmallIconMode = new MenuItem() { Header = "小图标(_I)", IsChecked = false, };
            miSmallIconMode.Click += miSmallIconMode_Click;
            this.contextMenu.Items.Add(miSmallIconMode);

            miMediumIconMode = new MenuItem() { Header = "中等图标(_M)", IsChecked = false, };
            miMediumIconMode.Click += MiMediumIconMode_Click;
            this.contextMenu.Items.Add(miMediumIconMode);

            miLargeIconMode = new MenuItem() { Header = "大图标(_L)", IsChecked = false, };
            miLargeIconMode.Click += MiLargeIconMode_Click;
            this.contextMenu.Items.Add(miLargeIconMode);

            miSuperLargeIconMode = new MenuItem() { Header = "特大图标(_S)", IsChecked = false, };
            miSuperLargeIconMode.Click += MiSuperLargeIconMode_Click;
            this.contextMenu.Items.Add(miSuperLargeIconMode);

            this.contextMenu.Items.Add(new Separator());

            miSetXamlText = new MenuItem() { Header = "粘贴 Lunar Concept 图标(_X)", };
            miSetXamlText.Click += miSetXamlText_Click;
            this.contextMenu.Items.Add(miSetXamlText);

            miClearXamlText = new MenuItem() { Header = "清除 Lunar Concept 页(_C)", };
            miClearXamlText.Click += MiClearXamlText_Click;
            this.contextMenu.Items.Add(miClearXamlText);

            miCopyXamlText = new MenuItem() { Header = "复制 Lunar Concept 页（_O)", };
            miCopyXamlText.Click += MiCopyXamlText_Click;
            this.contextMenu.Items.Add(miCopyXamlText);

            this.contextMenu.ContextMenuOpening += ContextMenu_ContextMenuOpening;

            this.Margin = baseMargin;

            this.baseBorder.PreviewMouseLeftButtonDown += BaseBorder_PreviewMouseLeftButtonDown;
            this.baseBorder.PreviewMouseRightButtonDown += mainImage_PreviewMouseRightButtonDown;
            this.baseBorder.PreviewMouseLeftButtonUp += BaseBorder_PreviewMouseLeftButtonUp;

            //添加装饰器（选取框）
            AdornerLayer adornerLayer = AdornerLayer.GetAdornerLayer(this.baseBorder);
            selectedAdorner = new TitleImageSelectedAdorner(this.baseBorder, this) { Visibility = Visibility.Hidden };
            adornerLayer.Add(selectedAdorner);
        }

        private void MiCopyXamlText_Click(object sender, RoutedEventArgs e)
        {
            if (this.xmlData == null) return;
            var node = this.xmlData.SelectSingleNode("LunarConcept");
            if (node == null) return;

            Clipboard.SetData(DataFormats.UnicodeText, "<LunarMind.Xaml>" + node.OuterXml + "</LunarMind.Xaml>");
        }

        private void MiClearXamlText_Click(object sender, RoutedEventArgs e)
        {
            if (masterTitle == null || masterTitle.ID == null || masterTitle.ID.Length <= 0)
            {
                MessageBox.Show("此图片构造异常。未传入它所在的标题，或所在标题的ID为空。无法继续设置其图像或图形。",
                    Globals.AppName, MessageBoxButton.OK, MessageBoxImage.Warning);
                return;
            }

            string imgDataText = "";

            XmlNode imgNode = this.XmlData;

            string oldImgText = imgNode.InnerXml;

            var mi = new ModifingItem()
            {
                IsNeedRefreshTitleAndLinesLocation = true,
                ModifingName = "清除标题图像数据",
            };

            Action action = new Action(this.ID, -1,
                this.GetType().Name, "ImageBase64",
                oldImgText, imgDataText, ActionType.Property, masterTitle.ID);
            mi.Add(action);

            this.XmlData.InnerXml = imgDataText;
            this.BuildTitleImage();

            //添加到“撤销”列表。
            Editor.Do(mi);
            editor.IsModified = true;
            editor.RefreshTitleAndLinesLocation();
        }

        private void MiSuperLargeIconMode_Click(object sender, RoutedEventArgs e)
        {
            if (this.mode == ImageMode.SuperLargeIcon) return;

            ModifingItem mi = new ModifingItem()
            {
                IsNeedRefreshTitleAndLinesLocation = true,
                ModifingName = "设置标题图像呈现模式为：特大图标",
            };

            Action actMode = new Action(this.ID, -1, this.GetType().Name, "Mode",
                this.Mode.ToString(), ImageMode.SuperLargeIcon.ToString());
            this.Mode = ImageMode.SuperLargeIcon;
            mi.Add(actMode);

            if (mi.ModifiedPropertyAndValues.Count > 0)
            {
                Globals.MainWindow.Do(mi);
                Globals.MainWindow.IsModified = true;
                Globals.MainWindow.RefreshTitleAndLinesLocation();
            }
        }

        private void MiLargeIconMode_Click(object sender, RoutedEventArgs e)
        {
            if (this.mode == ImageMode.LargeIcon) return;

            ModifingItem mi = new ModifingItem()
            {
                IsNeedRefreshTitleAndLinesLocation = true,
                ModifingName = "设置标题图像呈现模式为：大图标",
            };

            Action actMode = new Action(this.ID, -1, this.GetType().Name, "Mode",
                this.Mode.ToString(), ImageMode.LargeIcon.ToString());
            this.Mode = ImageMode.LargeIcon;
            mi.Add(actMode);

            if (mi.ModifiedPropertyAndValues.Count > 0)
            {
                Globals.MainWindow.Do(mi);
                Globals.MainWindow.IsModified = true;
                Globals.MainWindow.RefreshTitleAndLinesLocation();
            }
        }

        private void MiMediumIconMode_Click(object sender, RoutedEventArgs e)
        {
            if (this.mode == ImageMode.Icon) return;

            ModifingItem mi = new ModifingItem()
            {
                IsNeedRefreshTitleAndLinesLocation = true,
                ModifingName = "设置标题图像呈现模式为：中等图标",
            };

            Action actMode = new Action(this.ID, -1, this.GetType().Name, "Mode",
                this.Mode.ToString(), ImageMode.Icon.ToString());
            this.Mode = ImageMode.Icon;
            mi.Add(actMode);

            if (mi.ModifiedPropertyAndValues.Count > 0)
            {
                Globals.MainWindow.Do(mi);
                Globals.MainWindow.IsModified = true;
                Globals.MainWindow.RefreshTitleAndLinesLocation();
            }
        }

        private void BaseBorder_PreviewMouseLeftButtonUp(object sender, MouseButtonEventArgs e)
        {
            if (this.MasterTitle != null)
            {
                this.MasterTitle.DropOrLinkTitle();
            }
        }

        private void BaseBorder_PreviewMouseLeftButtonDown(object sender, MouseButtonEventArgs e)
        {
            //会清除所有对标题的选取。
            this.IsSelected = true;

            //这个属性会执行清除选取状态的操作。
            editor.SelectedTitleImage = this;

            e.Handled = true;
        }

        void miSetXamlText_Click(object sender, RoutedEventArgs e)
        {
            PasteConceptXamlToTitleImage();
        }

        public void PasteConceptXamlToTitleImage()
        {
            if (masterTitle == null || masterTitle.ID == null || masterTitle.ID.Length <= 0)
            {
                MessageBox.Show("此图片构造异常。未传入它所在的标题，或所在标题的ID为空。无法继续设置其图像或图形。",
                    Globals.AppName, MessageBoxButton.OK, MessageBoxImage.Warning);
                return;
            }

            string imgDataText = Clipboard.GetText(TextDataFormat.UnicodeText);

            imgDataText = imgDataText.Replace("<LunarMind.Xaml>", "").Replace("</LunarMind.Xaml>", "");

            XmlNode imgNode = this.XmlData;

            string oldImgText = imgNode.InnerXml;

            var mi = new ModifingItem()
            {
                IsNeedRefreshTitleAndLinesLocation = true,
                ModifingName = "设置标题图像数据",
            };

            Action action = new Action(this.ID, -1,
                this.GetType().Name, "ImageBase64",
                oldImgText, imgDataText, ActionType.Property, masterTitle.ID);
            mi.Add(action);

            this.XmlData.InnerXml = imgDataText;
            this.BuildTitleImage();

            //添加到“撤销”列表。
            Editor.Do(mi);
            editor.IsModified = true;
            editor.RefreshTitleAndLinesLocation();
        }

        public enum ImageType
        {
            BitmapImage, XamlElement
        }

        public string XamlText
        {
            get
            {
                if (this.xmlData == null) return string.Empty;
                if (IsBase64(this.xmlData.InnerXml)) return string.Empty;

                return this.xmlData.InnerXml;
            }
        }

        public ImageType ContentType
        {
            get
            {
                if (this.baseViewBox.Child == this.mainImage)
                    return ImageType.BitmapImage;
                else return ImageType.XamlElement;
            }
        }

        private Border baseBorder = new Border();

        private Viewbox baseViewBox = new Viewbox();

        void miImageTitle_Click(object sender, RoutedEventArgs e)
        {
            Dialogs.InputWindow iw = new Dialogs.InputWindow(Globals.MainWindow,
                "请输入图像标题（此标题将在演示图像时呈现在演示窗口顶部）：", this.Title, Globals.AppName, null, false);
            if (iw.ShowDialog() != true) return;

            string newTitleText = iw.InputedText;

            ModifingItem mi = new ModifingItem()
            {
                IsNeedRefreshTitleAndLinesLocation = true,
                ModifingName = "设置图标的标题文本"
            };

            Action actMode = new Action(this.ID, -1, this.GetType().Name, "Title",
                this.Title, newTitleText);
            this.Title = newTitleText;
            mi.Add(actMode);

            if (mi.ModifiedPropertyAndValues.Count > 0)
            {
                Globals.MainWindow.Do(mi);
                Globals.MainWindow.IsModified = true;
                //Globals.MainWindow.RefreshTitleAndLinesLocation();
            }
        }

        void miPresentateAllImage_Click(object sender, RoutedEventArgs e)
        {
            if (this.masterTitle == null) return;
            this.masterTitle.PresentateImages();
        }

        void miPresentateImage_Click(object sender, RoutedEventArgs e)
        {
            this.PresentateImage();
        }

        void mainImage_PreviewMouseRightButtonDown(object sender, MouseButtonEventArgs e)
        {
            //会清除所有对标题的选取。
            this.IsSelected = true;

            //这个属性会执行清除选取状态的操作。
            editor.SelectedTitleImage = this;
            e.Handled = true;

            this.contextMenu.IsOpen = true;
        }

        private ContextMenu contextMenu = new ContextMenu();

        private MenuItem miDefaultMode;

        private MenuItem miSmallIconMode;

        private MenuItem miMediumIconMode;

        private MenuItem miLargeIconMode;

        private MenuItem miSuperLargeIconMode;

        private MenuItem miSetXamlText;

        private MenuItem miClearXamlText;

        private MenuItem miCopyXamlText;

        void ContextMenu_ContextMenuOpening(object sender, ContextMenuEventArgs e)
        {
            miDefaultMode.IsChecked = false;
            miSmallIconMode.IsChecked = false;
            miMediumIconMode.IsChecked = false;
            miLargeIconMode.IsChecked = false;
            miSuperLargeIconMode.IsChecked = false;

            switch (this.mode)
            {
                case ImageMode.SmallIcon:
                    {
                        miSmallIconMode.IsChecked = true;
                        break;
                    }
                case ImageMode.Icon:
                    {
                        miMediumIconMode.IsChecked = true;
                        break;
                    }
                case ImageMode.LargeIcon:
                    {
                        miLargeIconMode.IsChecked = true;
                        break;
                    }
                case ImageMode.SuperLargeIcon:
                    {
                        miSuperLargeIconMode.IsChecked = true;
                        break;
                    }
                default:
                    {
                        miDefaultMode.IsChecked = true;
                        break;
                    }
            }
        }

        void miSmallIconMode_Click(object sender, RoutedEventArgs e)
        {
            if (this.mode == ImageMode.SmallIcon) return;

            ModifingItem mi = new ModifingItem()
            {
                IsNeedRefreshTitleAndLinesLocation = true,
                ModifingName = "设置标题图像呈现模式为：小图标"
            };

            Action actMode = new Action(this.ID, -1, this.GetType().Name, "Mode",
                this.Mode.ToString(), ImageMode.SmallIcon.ToString());
            this.Mode = ImageMode.SmallIcon;
            mi.Add(actMode);

            if (mi.ModifiedPropertyAndValues.Count > 0)
            {
                Globals.MainWindow.Do(mi);
                Globals.MainWindow.IsModified = true;
                Globals.MainWindow.RefreshTitleAndLinesLocation();
            }
        }

        void miDefaultMode_Click(object sender, RoutedEventArgs e)
        {
            if (this.mode == ImageMode.Default) return;

            ModifingItem mi = new ModifingItem()
            {
                IsNeedRefreshTitleAndLinesLocation = true,
                ModifingName = "设置标题图像呈现模式为：默认"
            };

            Action actMode = new Action(this.ID, -1, this.GetType().Name, "Mode",
                this.Mode.ToString(), ImageMode.Default.ToString());
            this.Mode = ImageMode.Default;
            mi.Add(actMode);

            if (mi.ModifiedPropertyAndValues.Count > 0)
            {
                Globals.MainWindow.Do(mi);
                Globals.MainWindow.IsModified = true;
                Globals.MainWindow.RefreshTitleAndLinesLocation();
            }
        }

        void miLoadImage_Click(object sender, RoutedEventArgs e)
        {
            LoadImageFromFile();
        }

        private string id = null;

        /// <summary>
        /// GUID字符串。
        /// </summary>
        public string ID
        {
            get { return id; }
        }

        private ImageMode mode = ImageMode.Default;

        public ImageMode Mode
        {
            get { return this.mode; }
            set
            {
                this.mode = value;
                if (this.xmlData != null)
                {
                    this.xmlData.SetAttribute("Mode", this.mode.ToString());
                }

                this.RefreshMode();
            }
        }

        private void RefreshMode()
        {
            Size size = this.baseViewBox.Child.RenderSize;
            if (size.Width <= 0) size.Width = 32;
            if (size.Height <= 0) size.Height = 32;

            switch (this.mode)
            {
                case ImageMode.SmallIcon:
                    {
                        if (size.Width > size.Height)
                        {
                            this.baseViewBox.Width = 48;
                            this.baseViewBox.Height = 48 * (size.Height / size.Width);
                        }
                        else
                        {
                            this.baseViewBox.Height = 48;
                            this.baseViewBox.Width = 48 * (size.Width / size.Height);
                        }
                        break;
                    }
                case ImageMode.Icon:
                    {
                        if (size.Width > size.Height)
                        {
                            this.baseViewBox.Width = 96;
                            this.baseViewBox.Height = 96 * (size.Height / size.Width);
                        }
                        else
                        {
                            this.baseViewBox.Height = 96;
                            this.baseViewBox.Width = 96 * (size.Width / size.Height);
                        }
                        break;
                    }
                case ImageMode.LargeIcon:
                    {
                        if (size.Width > size.Height)
                        {
                            this.baseViewBox.Width = 192;
                            this.baseViewBox.Height = 192 * (size.Height / size.Width);
                        }
                        else
                        {
                            this.baseViewBox.Height = 192;
                            this.baseViewBox.Width = 192 * (size.Width / size.Height);
                        }
                        break;
                    }
                case ImageMode.SuperLargeIcon:
                    {
                        if (size.Width > size.Height)
                        {
                            this.baseViewBox.Width = 384;
                            this.baseViewBox.Height = 384 * (size.Height / size.Width);
                        }
                        else
                        {
                            this.baseViewBox.Height = 384;
                            this.baseViewBox.Width = 384 * (size.Width / size.Height);
                        }
                        break;
                    }
                default:
                    {
                        this.baseViewBox.Width = this.baseViewBox.Height = double.NaN;

                        //BitmapImage srcBitmpaImage = mainImage.Source as BitmapImage;
                        //if (mainImage != null && srcBitmpaImage != null)
                        //{
                        //    mainImage.Width = srcBitmpaImage.PixelWidth;
                        //    mainImage.Height = srcBitmpaImage.PixelHeight;
                        //}
                        break;
                    }
            }
        }


        private Title masterTitle = null;

        public Title MasterTitle
        {
            get { return masterTitle; }
        }

        /// <summary>
        /// 会同时修改ID属性值及对应XmlData中的ID特性的值。
        /// </summary>
        public void RebuildANewID()
        {
            id = Guid.NewGuid().ToString();
            if (this.xmlData != null)
            {
                this.xmlData.SetAttribute("ID", id);
            }
        }

        public void PresentateImage()
        {
            ImagePresentationWindow ipw = new ImagePresentationWindow() { Owner = Globals.MainWindow, };
            ipw.backgroundRect.Fill = Globals.MainWindow.mainCanvas.Background;

            ipw.tbTitleText.Text = this.title;
            ipw.RefreshImageTitleText();

            if (this.ContentType == ImageType.BitmapImage)
            {
                ipw.mainImage.Source = this.mainImage.Source;

                BitmapImage bimg = this.mainImage.Source as BitmapImage;
                ipw.mainImage.Width = bimg.PixelWidth;
                ipw.mainImage.Height = bimg.PixelHeight;

                if (this.baseViewBox.Child != this.mainImage) this.baseViewBox.Child = this.mainImage;
            }
            else if (this.ContentType == ImageType.XamlElement)
            {
                ipw.mainImage.Visibility = System.Windows.Visibility.Hidden;

                try
                {
                    if (this.XamlText.StartsWith("<LunarConcept>") && this.XamlText.EndsWith("</LunarConcept>"))
                    {
                        ipw.baseViewBox.Visibility = System.Windows.Visibility.Hidden;

                        PageEditorReader per = new PageEditorReader();
                        var conceptNode = this.xmlData.SelectSingleNode(XmlTags.LunarConceptTag);
                        per.XmlData = conceptNode.SelectSingleNode(XmlTags.PageTag);
                        //per.Build();//设置XmlData属性值时会自动调用。

                        ipw.baseViewBox.Child = per;
                    }
                    else
                    {
                        if (string.IsNullOrEmpty(this.XamlText))
                        {
                            ipw.baseViewBox.Visibility = System.Windows.Visibility.Hidden;
                            ipw.mainImage.Source = TitleImage.defaultBitmap;
                        }
                        else
                        {
                            byte[] array = System.Text.Encoding.UTF8.GetBytes(this.XamlText);
                            using (var stream = new System.IO.MemoryStream(array))
                            {
                                ipw.xamlElement = System.Windows.Markup.XamlReader.Load(stream) as FrameworkElement;
                                ipw.xamlElement.HorizontalAlignment = System.Windows.HorizontalAlignment.Center;
                                ipw.xamlElement.VerticalAlignment = System.Windows.VerticalAlignment.Center;

                                if (ipw.baseViewBox.Child != ipw.xamlElement)
                                    ipw.baseViewBox.Child = ipw.xamlElement;
                            }
                        }
                    }
                }
                catch (Exception)
                {
                    ipw.baseViewBox.Visibility = System.Windows.Visibility.Hidden;
                    ipw.mainImage.Source = TitleImage.defaultBitmap;
                }

                ipw.baseViewBox.Visibility = System.Windows.Visibility.Visible;
            }

            ipw.ShowDialog();
        }

        internal void LoadImageFromFile(ModifingItem mi = null, string fileFullname = null)
        {
            if (masterTitle == null || masterTitle.ID == null || masterTitle.ID.Length <= 0)
            {
                MessageBox.Show("此图片构造异常。未传入它所在的标题，或所在标题的ID为空。无法继续设置其图像。",
                    Globals.AppName, MessageBoxButton.OK, MessageBoxImage.Warning);
                return;
            }

            string filename = "";

            if (fileFullname == null)
            {
                OpenFileDialog ofd = new OpenFileDialog();
                ofd.Multiselect = false;
                ofd.Title = Globals.AppName + "——请选择需要的图片：";
                ofd.Filter = "支持的所有图片格式(*.bmp;*.gif;*.jpg;*.jpeg;*.png;*.tiff)|*.bmp;*.gif;*.jpg;*.jpeg;*.png;*.tiff|" +
                    "PNG或JPEG图片(*.png;*.jpg;*.jpeg)|*.png;*.jpg;*.jpeg|" +
                    "联合图像专家组格式(*.jpg;*.jpeg)|*.jpg;*.jpeg|" +
                    "图形交换格式(*.gif)|*.gif|" +
                    "W3C 可移植网络图形(*png)|*png|" +
                    "标题图像文件(*.tiff)|*.tiff";

                if (ofd.ShowDialog() != true) return;

                filename = ofd.FileName;
            }
            else
            {
                filename = fileFullname;
            }

            System.IO.FileInfo fileInfo = new FileInfo(filename);

            if (fileInfo.Exists == false)
            {
                System.Windows.MessageBox.Show("文件不存在！", Globals.AppName,
                    MessageBoxButton.OK, MessageBoxImage.Warning);
                return;
            }

            if (fileInfo.Length <= 2097152)//将图片限制在2MB以内
            {
                System.Drawing.Image fileImg = System.Drawing.Image.FromFile(filename);
                using (System.IO.MemoryStream stream = new System.IO.MemoryStream())
                {
                    try
                    {
                        if (fileInfo.Extension.ToLower() == ".png")
                        {
                            fileImg.Save(stream, System.Drawing.Imaging.ImageFormat.Png);
                        }
                        else if (fileInfo.Extension.ToLower() == ".jpg" || fileInfo.Extension.ToLower() == ".jpeg")
                        {
                            fileImg.Save(stream, System.Drawing.Imaging.ImageFormat.Jpeg);
                        }
                        else if (fileInfo.Extension.ToLower() == ".gif")
                        {
                            fileImg.Save(stream, System.Drawing.Imaging.ImageFormat.Gif);
                        }
                        else if (fileInfo.Extension.ToLower() == ".tiff")
                        {
                            fileImg.Save(stream, System.Drawing.Imaging.ImageFormat.Tiff);
                        }
                        else if (fileInfo.Extension.ToLower() == ".bmp")
                        {
                            fileImg.Save(stream, System.Drawing.Imaging.ImageFormat.Bmp);
                        }
                        else
                        {
                            return;//不能识别的文件格式。
                        }

                        byte[] b = stream.GetBuffer();
                        string imgDataText = Convert.ToBase64String(b);

                        XmlNode imgNode = this.XmlData;

                        string oldImgText = imgNode.InnerText;
                        imgNode.InnerText = imgDataText;

                        //XmlData.SetAttribute("Width", fileImg.Width.ToString());
                        //XmlData.SetAttribute("Height", fileImg.Height.ToString());
                        //mainImage.Width = fileImg.Width;
                        //mainImage.Height = fileImg.Height;

                        mainImage.Source = new BitmapImage(new Uri(filename));
                        if (this.baseViewBox.Child != this.mainImage)
                        {
                            this.baseViewBox.Child = this.mainImage;
                        }

                        #region 准备“撤销”与“重做”数据。
                        if (mi == null)
                        {
                            mi = new ModifingItem()
                            {
                                IsNeedRefreshTitleAndLinesLocation = true,
                                ModifingName = "设置标题图像数据"
                            };
                        }


                        Action action = new Action(this.ID, -1,
                            this.GetType().Name, "ImageBase64",
                            oldImgText, imgDataText, ActionType.Property, masterTitle.ID);
                        mi.Add(action);


                        if (fileImg.Width > 200 || fileImg.Height > 200)
                        {
                            //标题中强迫尺寸过大的图像以图标模式呈现——除非用户手动更改模式。
                            //var result = MessageBox.Show("　　此图像高度或宽度大于200，要以【图标模式】呈现吗？", Globals.AppName, MessageBoxButton.YesNo, MessageBoxImage.Question);
                            //if (result == MessageBoxResult.Yes)
                            //{

                            if (this.Mode != ImageMode.SmallIcon)
                            {
                                Action actMode = new Action(this.ID, -1, this.GetType().Name, "Mode", this.Mode.ToString(), ImageMode.SmallIcon.ToString());
                                this.Mode = ImageMode.SmallIcon;
                                mi.Add(actMode);
                            }
                            //}
                        }
                        #endregion

                        this.RefreshMode();

                        //添加到“撤销”列表。
                        Editor.Do(mi);

                        editor.IsModified = true;
                        editor.RefreshTitleAndLinesLocation();
                    }
                    catch (System.Runtime.InteropServices.ExternalException ex)
                    {
                        Dialogs.LunarMsgBox.MsgBoxShow(
                            Globals.AppName,
                            "未能载入图片文件。",
                            "该图像以错误的图像格式后缀名保存！\r\n" + ex.Message,
                            ex.StackTrace, MessageBoxButton.OK, MessageBoxImage.Warning);
                    }
                }
                fileImg.Dispose();
            }
            else
            {
                Dialogs.LunarMsgBox.MsgBoxShow(
                     Globals.AppName,
                     "图片文件太大。",
                     "为防止文档体积过分庞大，本图片框只支持文件尺寸在 2MB 以下的图片！",
                     "请将图片加工一下或另选一张图片。",
                     MessageBoxButton.OK, MessageBoxImage.Warning);
                return;
            }
        }

        private static readonly Thickness baseMargin = new Thickness(8);

        private MainWindow editor;

        /// <summary>
        /// 所在的主窗口。
        /// </summary>
        public MainWindow Editor
        {
            get { return editor; }
            set { editor = value; }
        }

        private bool isSelected;

        /// <summary>
        /// 会清除所有选取的标题。且只能选取一个图片。
        /// </summary>
        public bool IsSelected
        {
            get { return isSelected; }
            set
            {
                isSelected = value;

                selectedAdorner.Visibility = value ? Visibility.Visible : Visibility.Hidden;
                selectedAdorner.InvalidateVisual();
            }
        }

        //private static string imgToolTip = "此处拖动无效";

        private Image mainImage = new Image(); //{ ToolTip = imgToolTip };
        /// <summary>
        /// [只读]与XamlElement不同时出现。当不存在Base64文本形式存储的图像数据时，尝试按Xaml来解析。
        /// </summary>
        public Image MainImage
        {
            get { return mainImage; }
            set { mainImage = value; }
        }

        private FrameworkElement xamlElement;
        /// <summary>
        /// [只读]与MainImage不同时出现。当不存在Base64文本形式存储的图像数据时，尝试按Xaml来解析。
        /// </summary>
        public FrameworkElement XamlElement
        {
            get { return xamlElement; }
        }

        /// <summary>
        /// 只读属性，取此图在父标题中的索引。
        /// </summary>
        public int Index
        {
            get
            {
                if (masterTitle == null) return -1;
                return masterTitle.ImgStackPanel.Children.IndexOf(this);
            }
        }

        private XmlNode xmlData;

        public XmlNode XmlData
        {
            get { return xmlData; }
            set
            {
                xmlData = value;
                BuildTitleImage();
            }
        }

        private Adorners.TitleImageSelectedAdorner selectedAdorner;

        public Adorners.TitleImageSelectedAdorner SelectedAdorenr
        {
            get { return selectedAdorner; }
            set { selectedAdorner = value; }
        }

        static TitleImage()
        {
            defaultBitmap = new BitmapImage(new Uri("pack://application:,,,/LunarMind;component/Resources/Icons/Image.png"));
            errorBitmap = new BitmapImage(new Uri("pack://application:,,,/LunarMind;component/Resources/Icons/error.png"));
            htmlTag = new BitmapImage(new Uri("pack://application:,,,/LunarMind;component/Resources/htmltag.png"));
            pictureTag = new BitmapImage(new Uri("pack://application:,,,/LunarMind;component/Resources/picturetag.png"));
        }

        public static System.Windows.Media.Imaging.BitmapImage defaultBitmap;

        public static System.Windows.Media.Imaging.BitmapImage errorBitmap;

        /// <summary>
        /// Html 文件链接点位符。
        /// </summary>
        public static System.Windows.Media.Imaging.BitmapImage htmlTag;

        /// <summary>
        /// 图像文件链接点位符。
        /// </summary>
        public static System.Windows.Media.Imaging.BitmapImage pictureTag;

        public void BuildTitleImage()
        {
            if (this.xmlData == null)
            {
                mainImage.Width = TitleImage.defaultBitmap.PixelWidth;
                mainImage.Height = TitleImage.defaultBitmap.PixelHeight;
                mainImage.Source = TitleImage.defaultBitmap;
                if (this.baseViewBox.Child != mainImage) this.baseViewBox.Child = mainImage;
                return;
            }

            try
            {
                XmlAttribute attrID = this.xmlData.GetAttribute("ID");
                if (attrID != null)
                {
                    this.id = attrID.Value;
                }
                else
                {
                    RebuildANewID();
                }

                XmlAttribute attrMode = this.xmlData.GetAttribute("Mode");
                if (attrMode != null)
                {
                    this.mode = (ImageMode)Enum.Parse(typeof(ImageMode), attrMode.Value);
                }

                XmlNode imgNode = this.XmlData;

                var attrLinkType = this.xmlData.GetAttribute("LinkType");
                if (attrLinkType != null && (attrLinkType.Value == "Html" || attrLinkType.Value == "Image"))
                {
                    if (attrLinkType.Value == "Html")
                    {
                        mainImage.Source = htmlTag;
                        this.baseViewBox.Child = mainImage;
                    }
                    else if(attrLinkType.Value == "Image")
                    {
                        mainImage.Source = pictureTag;
                        this.baseViewBox.Child = mainImage;
                    }
                }
                else
                {
                    //图片可能无数据。
                    string imgDataText = imgNode.InnerXml;
                    //要考虑XamlElement故改用InnerXml，原来只需要InnerText即可。2014年3月24日

                    try
                    {
                        BitmapImage bmp = new BitmapImage();

                        if (imgDataText != null && IsBase64(imgDataText))
                        {
                            byte[] b = Convert.FromBase64String(imgDataText);
                            bmp.BeginInit();
                            bmp.StreamSource = new MemoryStream(b);
                            bmp.EndInit();

                            mainImage.Source = bmp;
                            if (this.baseViewBox.Child != mainImage)
                            {
                                this.baseViewBox.Child = mainImage;
                            }
                        }
                        else
                        {
                            if (string.IsNullOrEmpty(imgDataText))
                            {
                                mainImage.Source = defaultBitmap;
                                if (this.baseViewBox.Child != mainImage)
                                {
                                    this.baseViewBox.Child = mainImage;
                                }
                            }
                            else
                            {
                                //bmp = TitleImage.defaultBitmap;//必为尝试按Xaml解析。
                                TryToLoadXamlElement(imgDataText);
                            }
                        }
                    }
                    catch (FormatException)
                    {
                        TryToLoadXamlElement(imgDataText);
                    }
                }

                this.RefreshMode();

                XmlAttribute attrRotateAngle = this.xmlData.GetAttribute("RotateAngle");
                if (attrRotateAngle != null)
                {
                    this.rotateAngle = double.Parse(attrRotateAngle.Value);
                    RefreshRotateAngle();
                }
            }
            catch (Exception ex)
            {
                Dialogs.LunarMsgBox.MsgBoxShow(Globals.AppName,
                    "图片构造时出现异常。异常信息如下：\r\n", ex.Message,
                    ex.StackTrace, MessageBoxButton.OK, MessageBoxImage.Warning, null, MessageBoxResult.OK,
                    Globals.MainWindow);
                return;
            }
        }

        private void TryToLoadXamlElement(string xamltext)
        {
            if (string.IsNullOrEmpty(xamltext)) return;

            if (xamltext.StartsWith("<LunarConcept>") && xamltext.EndsWith("</LunarConcept>"))
            {
                TryLoadConcept();
                return;
            }

            byte[] array = System.Text.Encoding.UTF8.GetBytes(xamltext);

            try
            {
                using (var stream = new System.IO.MemoryStream(array))
                {
                    this.xamlElement = System.Windows.Markup.XamlReader.Load(stream) as FrameworkElement;

                    this.baseViewBox.Child = this.xamlElement;

                    this.xamlElement.SizeChanged += xamlElement_SizeChanged;
                }
            }
            catch (Exception)
            {
                if (this.baseViewBox.Child != this.mainImage)
                    this.baseViewBox.Child = this.mainImage;
                this.mainImage.Source = TitleImage.errorBitmap;
            }
        }

        private void TryLoadConcept()
        {
            PageEditorReader per = new PageEditorReader();
            var conceptNode = this.xmlData.SelectSingleNode(XmlTags.LunarConceptTag);
            per.XmlData = conceptNode.SelectSingleNode(XmlTags.PageTag);
            //per.Build();//设置XmlData属性值时会自动调用。

            this.baseViewBox.Child = per;
        }

        void xamlElement_SizeChanged(object sender, SizeChangedEventArgs e)
        {
            if (editor != null) editor.RefreshTitleAndLinesLocation();
        }

        private static readonly HashSet<char> h = new HashSet<char>(){
            'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P',
            'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', 'a', 'b', 'c', 'd', 'e', 'f',
            'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v',
            'w', 'x', 'y', 'z', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '+', '/',
            '='};

        public static bool IsBase64(string s)
        {
            if (string.IsNullOrEmpty(s))
                return false;
            else if (s.Any(c => !h.Contains(c)))
                return false;

            return true;
            //转为图像数据时会自动再转，不需要重复。
            //try
            //{
            //    Convert.FromBase64String(s);
            //    return true;
            //}
            //catch (FormatException)
            //{
            //    return false;
            //}
        }

        private double rotateAngle = 0;

        public double RotateAngle
        {
            get { return rotateAngle; }
            set
            {
                if (value > 180)
                {
                    rotateAngle = 180;
                }
                else if (value < -180)
                {
                    rotateAngle = -180;
                }
                else
                {
                    rotateAngle = value;
                }

                if (this.xmlData != null)
                {
                    this.xmlData.SetAttribute("RotateAngle", rotateAngle.ToString());
                }

                RefreshRotateAngle();
            }
        }

        private static readonly Point defRenderCenter = new Point(0.5, 0.5);
        private static readonly RotateTransform defRotateTransform = new RotateTransform(0);

        private void RefreshRotateAngle()
        {
            if (this.RenderTransformOrigin != defRenderCenter)
            {
                this.RenderTransformOrigin = defRenderCenter;
            }

            if (rotateAngle == 0)
            {
                this.RenderTransform = defRotateTransform;
            }
            else
            {
                this.RenderTransform = new RotateTransform(rotateAngle);
            }
        }

        #region 实现INotifyPropertyChanged接口成员

        public event PropertyChangedEventHandler PropertyChanged;

        protected void OnPropertyChanged(object sender, PropertyChangedEventArgs e)
        {
            if (PropertyChanged != null)
            {
                PropertyChanged(sender, e);
            }
        }

        #endregion

        /// <summary>
        /// 一次公式级的撤销操作。
        /// </summary>
        /// <param name="action">一次撤销或重做可以涉及到多个公式（因而包含多次公式级的撤销或重做）。</param>
        public virtual void Undo(Action action)
        {
            if (action != null)
            {
                SetProperty(action.PropertyOrActionTypeName, action.OldValue);
            }
        }

        /// <summary>
        /// 一次公式级的重做操作。
        /// </summary>
        /// <param name="action"></param>
        public virtual void Redo(Action action)
        {
            if (action != null)
            {
                SetProperty(action.PropertyOrActionTypeName, action.NewValue);
            }
        }

        public virtual void SetProperty(string propertyName, string value)
        {
            switch (propertyName)
            {
                case "ImageBase64":
                    {
                        this.xmlData.InnerText = value;
                        BuildTitleImage();
                        break;
                    }
                case "RotateAngle":
                    {
                        this.RotateAngle = double.Parse(value); break;
                    }
                case "Mode":
                    {
                        this.Mode = (ImageMode)Enum.Parse(typeof(ImageMode), value); break;
                    }
                case "Title":
                    {
                        this.Title = value; break;
                    }
            }
        }

        private string title = string.Empty;

        public string Title
        {
            get { return this.title; }
            set
            {
                this.title = value;
                if (this.xmlData != null)
                {
                    this.xmlData.SetAttribute("Title", value);
                }
            }
        }
    }
}
